package org.frog.sgs.card.general;

import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

import org.frog.sgs.card.general.listener.GeneralEventListener;
import org.frog.sgs.card.general.listener.all.BaseEventListener;
import org.frog.sgs.event.SgsEvent;
import org.frog.sgs.event.SgsEventCode;
import org.frog.sgs.io.SgsMsg;

/**
 * @author duanxiangqi
 * @date 2012-10-28
 */
@SuppressWarnings("unchecked")
public enum GeneralEventDispatcher {
	instance;

	private Map<Integer, GeneralEventDetail> listeners = new LinkedHashMap<Integer, GeneralEventDetail>();
	{
		addListener(SgsEventCode.MY_ROUND_INIT, BaseEventListener.class, "myRoundInit");
		addListener(SgsEventCode.MY_ROUND_START, BaseEventListener.class, "myRoundStart");
		addListener(SgsEventCode.MY_JUDGE_START, BaseEventListener.class, "myJudgeStart");
		addListener(SgsEventCode.JUDGE_SCHEME, BaseEventListener.class, "judgeScheme");
		addListener(SgsEventCode.JUDGE_SCHEME_GET_JUDGE, BaseEventListener.class, "judgeSchemeGetJudge");
		addListener(SgsEventCode.JUDGE_SCHEME_RESULT, BaseEventListener.class, "judgeSchemeResult");
		addListener(SgsEventCode.JUDGE_SCHEME_EXECUTE, BaseEventListener.class, "judgeSchemeExecute");
		addListener(SgsEventCode.MY_GET_CARDS_START, BaseEventListener.class, "myGetCardsStart");
		addListener(SgsEventCode.GET_CARDS, BaseEventListener.class, "getCards");
		addListener(SgsEventCode.MY_USE_CARDS_START, BaseEventListener.class, "myUseCardsStart");
		addListener(SgsEventCode.USE_CARDS_PREPARE, BaseEventListener.class, "useCardsPrepare");
		addListener(SgsEventCode.USE_CARDS, BaseEventListener.class, "useCards");
		addListener(SgsEventCode.USE_SHA, BaseEventListener.class, "useSha");
		addListener(SgsEventCode.BEI_SHA, BaseEventListener.class, "beiSha");
		addListener(SgsEventCode.BEI_SHA_SHAN_ASK, BaseEventListener.class, "beiShaShanAsk");
		addListener(SgsEventCode.BEI_SHA_SHAN_RESULT, BaseEventListener.class, "beiShaShanResult");
		addListener(SgsEventCode.USE_SHA_RESULT, BaseEventListener.class, "useShaResult");
		addListener(SgsEventCode.USE_TAO, BaseEventListener.class, "useTao");
		addListener(SgsEventCode.USE_SCHEME, BaseEventListener.class, "useScheme");
		addListener(SgsEventCode.REDUCE_STRENGTH, BaseEventListener.class, "reduceStrength");
		addListener(SgsEventCode.ADD_STRENGTH, BaseEventListener.class, "addStrength");
		addListener(SgsEventCode.CLOSE_TO_DIE, BaseEventListener.class, "closeToDie");
		addListener(SgsEventCode.CLOSE_TO_DIE_ASK, BaseEventListener.class, "closeToDieAsk");
		addListener(SgsEventCode.DIE, BaseEventListener.class, "die");
		addListener(SgsEventCode.BA_GUA_DUN_ASK, BaseEventListener.class, "baGuaDunAsk");
		addListener(SgsEventCode.BA_GUA_DUN_RESULT, BaseEventListener.class, "baGuaDunResult");
		addListener(SgsEventCode.QI_LIN_GONG, BaseEventListener.class, "qiLinGong");
		addListener(SgsEventCode.FANG_TIAN_HUA_JI, BaseEventListener.class, "fangTianHuaJi");
		addListener(SgsEventCode.ZHANG_BA_SHE_MAO, BaseEventListener.class, "zhangBaSheMao");
		addListener(SgsEventCode.QING_LONG_YAN_YUE_DAO, BaseEventListener.class, "qingLongYanYueDao");
		addListener(SgsEventCode.GUAN_SHI_FU, BaseEventListener.class, "guanShiFu");
		addListener(SgsEventCode.HAN_BING_JIAN_ASK, BaseEventListener.class, "hanBingJianAsk");
		addListener(SgsEventCode.HAN_BING_JIAN_RESULT, BaseEventListener.class, "hanBingJianResult");
		addListener(SgsEventCode.CI_XIONG_SHUANG_GU_JIAN_ASK, BaseEventListener.class, "ciXiongShuangGuJianAsk");
		addListener(SgsEventCode.CI_XIONG_SHUANG_GU_JIAN_RESULT, BaseEventListener.class, "ciXiongShuangGuJianResult");
		addListener(SgsEventCode.BEI_SCHEME, BaseEventListener.class, "beiScheme");
		addListener(SgsEventCode.WU_XIE_KE_JI_ASK, BaseEventListener.class, "wuXieKeJiAsk");
		addListener(SgsEventCode.WU_XIE_KE_JI_RESULT, BaseEventListener.class, "wuXieKeJiResult");
		addListener(SgsEventCode.SHAN_DIAN, BaseEventListener.class, "shanDian");
		addListener(SgsEventCode.LE_BU_SI_SHU, BaseEventListener.class, "leBuSiShu");
		addListener(SgsEventCode.JIE_DAO_SHA_REN, BaseEventListener.class, "jieDaoShaRen");
		addListener(SgsEventCode.BEI_JIE_DAO_SHA_REN, BaseEventListener.class, "beiJieDaoShaRen");
		addListener(SgsEventCode.WU_GU_FENG_DENG, BaseEventListener.class, "wuGuFengDeng");
		addListener(SgsEventCode.WU_GU_FENG_DENG_EXECUTE, BaseEventListener.class, "wuGuFengDengExecute");
		addListener(SgsEventCode.WU_ZHONG_SHENG_YOU, BaseEventListener.class, "wuZhongShengYou");
		addListener(SgsEventCode.WU_ZHONG_SHENG_YOU_EXECUTE, BaseEventListener.class, "wuZhongShengYouExecute");
		addListener(SgsEventCode.TAO_YUAN_JIE_YI, BaseEventListener.class, "taoYuanJieYi");
		addListener(SgsEventCode.TAO_YUAN_JIE_YI_EXECUTE, BaseEventListener.class, "taoYuanJieYiExecute");
		addListener(SgsEventCode.NAN_MAN_RU_QIN, BaseEventListener.class, "nanManRuQin");
		addListener(SgsEventCode.NAN_MAN_RU_QIN_NEED_SHA_ASK, BaseEventListener.class, "nanManRuQinNeedShaAsk");
		addListener(SgsEventCode.NAN_MAN_RU_QIN_NEED_SHA_RESULT, BaseEventListener.class, "nanManRuQinNeedShaResult");
		addListener(SgsEventCode.WAN_JIAN_QI_FA, BaseEventListener.class, "wanJianQiFa");
		addListener(SgsEventCode.WAN_JIAN_QI_FA_NEED_SHAN_ASK, BaseEventListener.class, "wanJianQiFaNeedShanAsk");
		addListener(SgsEventCode.WAN_JIAN_QI_FA_NEED_SHAN_RESULT, BaseEventListener.class, "wanJianQiFaNeedShanResult");
		addListener(SgsEventCode.SHUN_SHOU_QIAN_YANG, BaseEventListener.class, "shunShouQianYang");
		addListener(SgsEventCode.SHUN_SHOU_QIAN_YANG_EXECUTE, BaseEventListener.class, "shunShouQianYangExecute");
		addListener(SgsEventCode.GUO_HE_CHAI_QIAO, BaseEventListener.class, "guoHeChaiQiao");
		addListener(SgsEventCode.GUO_HE_CHAI_QIAO_ASK, BaseEventListener.class, "guoHeChaiQiaoAsk");
		addListener(SgsEventCode.GUO_HE_CHAI_QIAO_EXECUTE, BaseEventListener.class, "guoHeChaiQiaoExecute");
		addListener(SgsEventCode.JUE_DOU, BaseEventListener.class, "jueDou");
		addListener(SgsEventCode.JUE_DOU_EXECUTE, BaseEventListener.class, "jueDouExecute");
		addListener(SgsEventCode.JUE_DOU_NEED_SHA_ASK, BaseEventListener.class, "jueDouNeedShaAsk");
		addListener(SgsEventCode.JUE_DOU_NEED_SHA_RESULT, BaseEventListener.class, "jueDouNeedShaResult");
		addListener(SgsEventCode.MY_GIVEUP_CARDS_START, BaseEventListener.class, "myGiveupCardsStart");
		addListener(SgsEventCode.GIVEUP_CARDS_ASK, BaseEventListener.class, "giveupCardsAsk");
		addListener(SgsEventCode.GIVEUP_CARDS_EXECUTE, BaseEventListener.class, "giveupCardsExecute");
		addListener(SgsEventCode.MY_ROUND_END, BaseEventListener.class, "myRoundEnd");
		addListener(SgsEventCode.ROUND_END_EXECUTE, BaseEventListener.class, "roundEndExecute");

	}

	public void dispatch(General general, SgsMsg msg) {
		int code = msg.getCode();
		SgsEvent last = general.getCharacter().getInstance().getEventManager().getLast();
		if (last == null) {
			System.err.println(general.getCharacter().getViewName() + "当前没有待处理事件");
		} else if (code == last.getCode() && general.getCharacter() == last.getCharacter()) {
			GeneralEventDetail detail = listeners.get(msg.getCode());
			try {
				Class clazz = detail.getClazz();
				Method method = clazz.getDeclaredMethod(detail.getMethodName(), SgsMsg.class);
				method.invoke(general, msg);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			System.err.println(general.getCharacter().getViewName() + "无法处理事件" + code + "；当前事件为："
					+ last.getCharacter().getViewName() + "{" + last.getCode() + "}");
		}
	}

	public <T extends GeneralEventListener> void addListener(int code, Class<T> clazz, String methodName) {
		listeners.put(code, new GeneralEventDetail(code, clazz, methodName));
	}

	class GeneralEventDetail<T extends GeneralEventListener> {

		private int code;

		private Class<T> clazz;

		private String methodName;

		public GeneralEventDetail(int code, Class<T> clazz, String methodName) {
			this.code = code;
			this.clazz = clazz;
			this.methodName = methodName;
		}

		public int getCode() {
			return code;
		}

		public void setCode(int code) {
			this.code = code;
		}

		public String getMethodName() {
			return methodName;
		}

		public void setMethodName(String methodName) {
			this.methodName = methodName;
		}

		public Class<T> getClazz() {
			return clazz;
		}

		public void setClazz(Class<T> clazz) {
			this.clazz = clazz;
		}
	}
}
